package com.godpaper.the5elements.busniess.AI
{
	import com.godpaper.the5elements.busniess.managers.PiecesManager;
	import com.godpaper.the5elements.model.BoardModel;
	import com.godpaper.the5elements.model.PiecesModel;
	import com.godpaper.the5elements.util.PositionTransactUtil;
	import com.godpaper.the5elements.views.components.GasketButton;
	import com.godpaper.the5elements.views.components.PieceButton;
	import com.godpaper.the5elements.vo.ConductVO;
	
	import de.polygonal.ds.Array2;
	
	import jp.dip.hael.gameai.graph.searcher.BFS;
	
	import mx.collections.ArrayCollection;
	import mx.logging.ILogger;
	import mx.logging.Log;
	
	 /**
	 * @author Knight-errant
	 * This essay is a detailed explanation of one of the most important
	 * data structures ever created for Game Artificial Intelligence. 
	 * The minimax tree is at the heart of almost every board game program in existence.
	 */	
	public class GameAIBase implements IAIBehavior
	{
		protected var bestMove:ConductVO;
		protected var moves:ArrayCollection;//conductVO's collection;
		protected var tempMove:ConductVO;
		protected var positionEvaluation:int;
		
		private static const log:ILogger = Log.getLogger("GameAIBase");
		
		public function GameAIBase()
		{
			//TODO: implement function
		}
		
		//return all possbility movements;
		public function generateMoves(reds:ArrayCollection, gamePosition:Array2):ArrayCollection
		{
			/*var funcName:String = new Error().getStackTrace();
			funcName = funcName.substring( funcName.indexOf("/")+1,funcName.indexOf("["));
			log.info("{0} begin!",funcName);*/
			log.info("generateMoves()");
			var tempAC:ArrayCollection = new ArrayCollection();
			log.debug("current GamePosition:{0}",BoardModel.getInstance().gamePosition.dump());
			for(var i:int=0;i<reds.length;i++)
			{
				var redsPB:PieceButton = reds.getItemAt(i) as PieceButton;
				var redsGB:GasketButton = PiecesModel.getInstance().gasketCollection.getItemAt( PositionTransactUtil.transactArray2Index((reds.getItemAt(i) as PieceButton).pieceVO.position)) as GasketButton;
				log.debug("current redsPB:{0}",redsPB);
				var redsGBnodeIndex:int = PositionTransactUtil.transactArray2Index( redsGB.position );
				log.debug("current redsGBnodeIndex:{0}",redsGBnodeIndex);
				//TODO:
				for(var j:int=0;j<BoardModel.getInstance().walkableGBindexs.length;j++)
				{
					var bfs:BFS = new BFS(BoardModel.getInstance().gameGraph);
					bfs.searchAll(  redsGBnodeIndex,
									BoardModel.getInstance().walkableGBindexs.getItemAt(j) as int,
									new ArrayCollection([redsGBnodeIndex]) );
					for(var p:int=0;p<bfs.allSimplePaths.length;p++)
					{
						log.debug("bfs found:{0}",bfs.allSimplePaths.getItemAt(p));
						var tailerGB:GasketButton = PiecesModel.getInstance().gasketCollection.getItemAt(bfs.allSimplePaths.length-1) as GasketButton;
						var conductVO:ConductVO = new ConductVO();
						conductVO.target = redsPB;
						conductVO.newDest = tailerGB.centerPointXY;
						conductVO.newPosition = tailerGB.position;
						tempAC.addItem(conductVO);
					}
//					var walkablePaths:Array = bfs.allSimplePaths;
				}
				/*for(var w:int=0;w<BoardModel.getInstance().gasketsPosition.width;w++)
				{
					for(var h:int=0;h<BoardModel.getInstance().gasketsPosition.height;h++)
					{
						if(BoardModel.getInstance().gasketsPosition.gett(w,h) is GasketButton)
						{
							var walkableGBnodeIndex:int = PositionTransactUtil.transactArray2Index( [w,h] );
							trace("walkableGBnodeIndex:",walkableGBnodeIndex); 
							var bfs:BFS = new BFS(BoardModel.getInstance().gameGraph);
							bfs.searchAll( redsGBnodeIndex,walkableGBnodeIndex,new ArrayCollection([redsGBnodeIndex]) );
							for(var len:int=0;len<bfs.allSimplePaths.length;len++)
							{
								if(bfs.allSimplePaths.getItemAt(len).length<5)
								{
									var simplePath:Array = bfs.allSimplePaths.getItemAt(len) as Array;
									trace("got simple path:",simplePath);
									var tailerGB:GasketButton = PiecesModel.getInstance().gasketCollection.getItemAt(simplePath.length-1) as GasketButton;
									trace("tailerGB in simple path:",tailerGB);
									var conductVO:ConductVO = new ConductVO();
									conductVO.target = redsPB;
									conductVO.newDest = tailerGB.centerPointXY;
									conductVO.newPosition = tailerGB.position;
									tempAC.addItem(conductVO);
								}
							}
						}	
					}
				}*/
				
				var redsPBleft:* = BoardModel.getInstance().gamePosition.gett( redsPB.pieceVO.position[0]-1,redsPB.pieceVO.position[1] );
				var redsPBtop:* = BoardModel.getInstance().gamePosition.gett( redsPB.pieceVO.position[0],redsPB.pieceVO.position[1]-1 );
				var redsPBright:* = BoardModel.getInstance().gamePosition.gett( redsPB.pieceVO.position[0]+1,redsPB.pieceVO.position[1] );
				var redsPBbottom:* = BoardModel.getInstance().gamePosition.gett( redsPB.pieceVO.position[0],redsPB.pieceVO.position[1]+1 );
				log.debug("redsPBleft:{0}",redsPBleft);
				log.debug("redsPBtop:{0}",redsPBtop);
				log.debug("redsPBright:{0}",redsPBright);
				log.debug("redsPBbottom:{0}",redsPBbottom);
				
				var redsPBleftGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett( redsPB.pieceVO.position[0]-1,redsPB.pieceVO.position[1]) as GasketButton;
				var redsPBtopGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett( redsPB.pieceVO.position[0],redsPB.pieceVO.position[1]-1) as GasketButton;
				var redsPBrightGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett( redsPB.pieceVO.position[0]+1,redsPB.pieceVO.position[1]) as GasketButton;
				var redsPBbottomGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett( redsPB.pieceVO.position[0],redsPB.pieceVO.position[1]+1) as GasketButton;
				
				log.debug("redsPBleftGB:{0}",redsPBleftGB);
				log.debug("redsPBtopGB:{0}",redsPBtopGB);
				log.debug("redsPBrightGB:{0}",redsPBrightGB);
				log.debug("redsPBbottomGB:{0}",redsPBbottomGB);
				//left
				if(redsPBleft==null && redsPBleftGB!=null)
				{
					var conductVOleft:ConductVO = new ConductVO();
					conductVOleft.target = redsPB;
					conductVOleft.newDest = redsPBleftGB.centerPointXY;
					conductVOleft.newPosition = redsPBleftGB.position;
					tempAC.addItem(conductVOleft);
				}
				//top
				if(redsPBtop==null && redsPBtopGB!=null)
				{
					var conductVOtop:ConductVO = new ConductVO();
					conductVOtop.target = redsPB;
					conductVOtop.newDest = redsPBtopGB.centerPointXY;
					conductVOtop.newPosition = redsPBtopGB.position;
					tempAC.addItem(conductVOtop);
				}
				//right
				if(redsPBright==null && redsPBrightGB!=null)
				{
					var conductVOright:ConductVO = new ConductVO();
					conductVOright.target = redsPB;
					conductVOright.newDest = redsPBrightGB.centerPointXY;
					conductVOright.newPosition = redsPBrightGB.position;
					tempAC.addItem(conductVOright);
				}
				//bottom
				if(redsPBbottom==null && redsPBbottomGB!=null)
				{
					var conductVObottom:ConductVO = new ConductVO();
					conductVObottom.target = redsPB;
					conductVObottom.newDest = redsPBbottomGB.centerPointXY;
					conductVObottom.newPosition = redsPBbottomGB.position;
					tempAC.addItem(conductVObottom);
				}
			}
			log.info("all possibility moves:");
			for(var z:int=0;z<tempAC.length;z++)
			{
				trace("\t moves[",z,"]:",
					(tempAC.getItemAt(z) as ConductVO).target,
					"[",
					(tempAC.getItemAt(z) as ConductVO).target.pieceVO.position,
					"]",
					"to [",
					(tempAC.getItemAt(z) as ConductVO).newPosition,
					"]");
			}
			log.info("~generateMoves()");
			return tempAC;
		}
		
		public function applyMovement(conductVO:ConductVO):Array2
		{
			PiecesModel.getInstance().selectedPiece = conductVO.target;
			log.debug("PiecesModel.getInstance().selectedPiece@GameAIBase.applyMove:{0}",PiecesModel.getInstance().selectedPiece);
			PiecesManager.tryMovement( conductVO.target,conductVO.newDest,conductVO.newPosition );
			return BoardModel.getInstance().gamePosition;
		}
		
		public function doEvaluation(conductVO:ConductVO):int
		{
			//TODO: implement function
			return positionEvaluation;
		}
	}
}